package com.ai.service.made.impl;


import cn.hutool.core.date.DateTime;
import com.ai.common.CommonResponse;

import com.ai.entity.BasePage;
import com.ai.entity.cameraFunctions.functions.CameraFunctionBindBO;
import com.ai.entity.cameraFunctions.functions.CameraFunctionsPO;
import com.ai.entity.file.Audio;
import com.ai.entity.file.Video;
import com.ai.entity.file.VideoPage;
import com.ai.entity.function.FunctionPO;
import com.ai.entity.made.camera.*;
import com.ai.entity.server.ServerPO;
import com.ai.mapper.made.VideoMapper;
import com.ai.service.made.*;
import com.ai.util.HttpRequestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * (Video)表服务实现类
 *
 * @author makejava
 * @since 2024-06-18 14:36:59
 */
@Slf4j
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {


    @Resource
    Environment environment;

    @Resource
    FunctionService functionService;

    @Resource
    CameraFunctionsService cameraFunctionsService;

    @Resource
    VideoMapper videoMapper;

    @Resource
    CameraService cameraService;

    @Resource
    ServerService serverService;

    @Resource
    TimeIntervalService timeIntervalService;

    @Resource
    RegionsService regionsService;

    @Value("${api.live.url}")
    private String liveUrl;

    public static ExecutorService executorService = Executors.newFixedThreadPool(10);


    @Override
    @Transactional
    public CommonResponse upload(MultipartFile[] files, Integer functionType) {


        if (files.length == 0) {
            return CommonResponse.error("文件不能为空");
        }
        long l = System.currentTimeMillis();
        for (MultipartFile file : files) {
            //获取文件存储的地址
            String videoUrl =   environment.getProperty("videoUploadPath.url");

            //获取文件名
            String fileName = file.getOriginalFilename();

            String urlName = videoUrl + fileName;

            Video video = getOne(new QueryWrapper<Video>().eq("video_name", fileName));

            File file1 = new File(videoUrl, fileName);

            if (video != null || file1.exists()) {
                log.info("文件已存在,该文件的文件名为{}", fileName);
                continue;
            }
            File file2 = new File(videoUrl);
            //创建需要存储音频的文件夹
            if (!file2.exists()) {
                boolean mkdir = file2.mkdir();
                if (!mkdir) {
                    log.error("创建文件夹异常");
                }
            }
            try {
                //获取文件输入流
                InputStream inputStream = file.getInputStream();
                //构建文件输出流
                FileOutputStream outputStream = new FileOutputStream(urlName);

                byte[] bytes = new byte[1024];
                int bytesread;
                while ((bytesread = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, bytesread);
                }

                Video video1 = new Video();
                video1.setVideoName(fileName);
                video1.setUrl(videoUrl);
                video1.setFunctionType(functionType);
                video1.setCreateTime(DateTime.now());
                video1.setIsState(2);
                video1.setUpdateTime(DateTime.now());

                save(video1);
                log.info("保存的录像信息为：{}", video1);
                outputStream.close();
                inputStream.close();

                //开启算法
                CommonResponse commonResponse = bulkSwitchForlive(functionType);
                //返回结果码：1成功，-1失败
                if (commonResponse.getCode() != 200) {
                    return commonResponse;
                }
                video1.setIsState(1);
                updateById(video1);

            } catch (IOException e) {
                log.error("录像文件上传异常,{}", e.getMessage());
                e.printStackTrace();
            }
        }
        long l1 = System.currentTimeMillis();
        log.info("上传" + files.length + "个音频文件花费时间,{}", (l1 - l) / 1000);
        return CommonResponse.ok("录像文件上传成功");
    }



    private CommonResponse bulkSwitchForlive(Integer functionType){
        int state = 2;
        //开始准备算法入参
        log.info("===========开始准备算法入参==========");
        //根据检测类型type查询检测类型相关信息
        FunctionPO funByType = functionService.getFunByType(functionType);
        //根据所需要检测的功能查询摄像头
        List<SwitchCameraAlgorithmBO> cameraByType = cameraFunctionsService.getCameraByType(funByType);

        CameraFunctionBindBO cameraFunctionBindBO = new CameraFunctionBindBO();
        List<Integer> functionIds = new ArrayList<>();
        functionIds.add(funByType.getId());
        //TODO 待优化
        SwitchCameraAlgorithmBO switchCameraAlgorithmBO = cameraByType.get(1);

        cameraFunctionBindBO.setCameraId(switchCameraAlgorithmBO.getCameraId());
        cameraFunctionBindBO.setFunctionIds(functionIds);

        cameraFunctionsService.checked(cameraFunctionBindBO);

        //获取摄像头的id
        int cameraId = switchCameraAlgorithmBO.getCameraId();

        CameraPO cameraPO = cameraService.getById(cameraId);
        //服务器id
        int serverId = cameraPO.getServerId();
        if (serverId == 0) {
            return CommonResponse.error("该摄像头未绑定服务器");
        }
        //        通过服务器ip获取对应的服务器
        ServerPO server = serverService.getById(serverId);
        if (null == server) {
            return CommonResponse.error("服务器不存在，请检查摄像头后重新操作");
        }
        String ip = server.getIp();
        Integer port = server.getPort();
        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || port == 0) {
            return CommonResponse.error("该摄像头所绑定服务器未设置IP或端口");
        }
        //TODO 待优化
        String url = ("http://" + ip + ":" + port + "/") + liveUrl;

        List<SwitchCameraFunctionAlgorithmBO> functionAlgorithmBOList = getAlgorithmFunctions(cameraId);

        String param;

        //打开直播

        BeanUtils.copyProperties(cameraPO, switchCameraAlgorithmBO);
        switchCameraAlgorithmBO.setCameraId(cameraId);
        switchCameraAlgorithmBO.setCameraCode(cameraPO.getCode());
        switchCameraAlgorithmBO.setIsVideo(2);
        switchCameraAlgorithmBO.setFunctions(functionAlgorithmBOList);
        log.info("------[ {} ]开启直播", cameraPO.getCode());

        switchCameraAlgorithmBO.setState(state);
        switchCameraAlgorithmBO.setStatus(state);

        param = JSONObject.toJSONString(switchCameraAlgorithmBO);


        log.info("===========================  算法入参：{}  ===========================", param);


        String sr = HttpRequestUtil.sendPost(url, param);

        //会返会null字符串么
        if (StringUtils.isEmpty(sr) || "null".equals(sr)) {
            return CommonResponse.error("网络请求失败！");
        }
        //解析算法返回数据
        JSONObject jsonObject = JSONObject.parseObject(sr);
        String alReturnJson = jsonObject.toJSONString();

        log.info("===========================  算法返回数据：{} ===========================", alReturnJson);

        //返回结果码：1成功，-1失败
        int result = Integer.valueOf(jsonObject.getString("resultCode"));
        String msg = jsonObject.getString("resultMsg");
        if (result == -1) {
            return CommonResponse.error("摄像头操作失败：" + msg);
        }
        return CommonResponse.ok("操作成功");

    }




    /**
     * 获取摄像头所绑定方法的所有区域信息
     *
     * @param cameraId
     * @return
     */
    private List<SwitchCameraFunctionAlgorithmBO> getAlgorithmFunctions(int cameraId) {
        //获取当前摄像头所绑定的所有方法
        ArrayList<SwitchCameraFunctionAlgorithmBO> functionList = new ArrayList<>();
        List<CameraFunctionsPO> cameraFunctionsPOList = cameraFunctionsService.getBindFunctions(cameraId);


        for (CameraFunctionsPO cameraFunctionsPO : cameraFunctionsPOList) {

            FunctionPO functionPO = functionService.getById(cameraFunctionsPO.getFunctionId());
            int type = functionPO.getType();

            SwitchCameraFunctionAlgorithmBO functionAlgorithmBO = new SwitchCameraFunctionAlgorithmBO();
            functionAlgorithmBO.setId(cameraFunctionsPO.getId()).setType(type + "")
                    .setThreshold(cameraFunctionsPO.getThreshold())
                    .setSpecialOne(cameraFunctionsPO.getSpecialOne())
                    .setSpecialThree(cameraFunctionsPO.getSpecialTwo())
                    .setSpecialThree(cameraFunctionsPO.getSpecialThree())
                    .setSpecialFour(cameraFunctionsPO.getSpecialFour())
                    .setSpecialFive(cameraFunctionsPO.getSpecialFive())
                    .setTimeIntervals(timeIntervalService.getTimeIntervalList(cameraFunctionsPO.getId()))
                    .setSpots(regionsService.getSpots(cameraFunctionsPO.getId()));
            functionList.add(functionAlgorithmBO);
        }

        return functionList;
    }


    @Override
    public CommonResponse delete(Video video) {

        if (ObjectUtils.isEmpty(video.getId())) {
            return CommonResponse.error("录像Id为空");
        }
        Video video1 = videoMapper.selectById(video.getId());
        String videoName = video1.getVideoName();
        //获取文件存储的地址
        String url = environment.getProperty("videoUploadPath.url");
        //删除本地文件
        File file = new File(url, videoName);
        if (!file.exists()) {
            return CommonResponse.error("文件不存在。删除失败");
        } else {
            file.delete();
            removeById(video1.getId());
            return CommonResponse.ok("删除成功");
        }
    }

    @Override
    public CommonResponse videoList(VideoPage videoPage) {
        IPage<Video> voIPage = new BasePage<>();
        QueryWrapper<Video> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time")
                .eq("is_state", 2);
        IPage<Video> page = page(voIPage, queryWrapper);
        return CommonResponse.ok(page);
    }
}

